public class Position implements Cloneable {
    private int x;
    private int y;
    private final int MAX_X;
    private final int MAX_Y;

    private final int DEFAULT_POSITION = 1;

    /**
     * this constructor create random position
     */

    public Position(int maxX, int maxY) {
        if (maxX > 0) {
            MAX_X = maxX;
        } else {
            MAX_X = DEFAULT_POSITION;
        }
        if (maxY > 0) {
            MAX_Y = maxY;
        } else {
            MAX_Y = DEFAULT_POSITION;
        }
        x = Randomize.getRandomNum(MAX_X);
        y = Randomize.getRandomNum(MAX_Y);

    }

    public Position(int x, int y, int maxX, int maxY) {
        if (maxX > 0) {
            MAX_X = maxX;
        } else {
            MAX_X = DEFAULT_POSITION;
        }
        if (maxY > 0) {
            MAX_Y = maxY;
        } else {
            MAX_Y = DEFAULT_POSITION;
        }

        if (x >= 0 && x < MAX_X) {
            this.x = x;
        } else {
            System.out.println("Error x");
            this.x = 0;
        }
        if (y >= 0 && y < MAX_Y) {
            this.y = y;
        } else {
            System.out.println("Error y");
            this.y = 0;
        }

    }

    public boolean equals(Position position) {
        return x == position.x && y == position.y;
    }

    public static Position getNewPosition(final Position oldPosition, MotionInformation motionInformation) {
        Position newPosition = oldPosition.clone();
        newPosition.changePosition(motionInformation);
        return newPosition;
    }

    @Override
    public Position clone() {
        try {
            Position obj = (Position) super.clone();
            obj.x = x;
            obj.y = y;
            return obj;
        } catch (CloneNotSupportedException e) {
            throw new AssertionError(e);
        }

    }
    public void changePosition(Direction direction,int step){
        changePosition(new MotionInformation(direction,step));
    }

    public void changePosition(MotionInformation motionInformation) {
        Direction direction=motionInformation.getDirection();
        int step=motionInformation.getStep();
        while (step > 0) {
            if (y % 2 == 1) {
                changePositionOdd(direction);
            } else {
                changePositionEven(direction);
            }
            step--;
        }
    }

    private void changePositionOdd(Direction direction) {
        switch (direction) {
            case LEFT:
                if (x - 1 >= 0) {
                    x -= 1;
                }
                break;

            case RIGHT:
                if (x + 1 < MAX_X) {
                    x += 1;
                }
                break;

            case UP_RIGHT:
                if (y - 1 >= 0 && x + 1 < MAX_X) {
                    y -= 1;
                    x += 1;
                }
                break;

            case UP_LEFT:
                if (y - 1 >= 0) {
                    y -= 1;
                }
                break;

            case DOWN_RIGHT:
                if (y + 1 < MAX_Y && x + 1 < MAX_X) {
                    y += 1;
                    x += 1;
                }
                break;

            case DOWN_LEFT:
                if (y + 1 < MAX_Y) {
                    y += 1;
                }
                break;

            default:
                break;
        }
    }

    private void changePositionEven(Direction direction) {
        switch (direction) {
            case LEFT:
                if (x - 1 >= 0) {
                    x -= 1;
                }
                break;

            case RIGHT:
                if (x + 1 < MAX_X) {
                    x += 1;
                }
                break;

            case UP_RIGHT:
                if (y - 1 >= 0) {
                    y -= 1;
                }
                break;

            case UP_LEFT:
                if (y - 1 >= 0 && x - 1 >= 0) {
                    y -= 1;
                    x -= 1;
                }
                break;

            case DOWN_RIGHT:
                if (y + 1 < MAX_Y) {
                    y += 1;
                }
                break;

            case DOWN_LEFT:
                if (y + 1 < MAX_Y && x - 1 >= 0) {
                    y += 1;
                    x -= 1;
                }
                break;

            default:
                break;
        }
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    public String toString() {
        return String.format("%d, %d", this.x, this.y);
    }
}
